Module 3

RTOS and IDE for Embedded System Design:

Operating System basics, Types of operating systems, Task, process and threads (Only POSIX Threads with an example program), Thread pre-emption, Preemptive Task scheduling techniques, Task Communication, Task synchronization issues – Racing and Deadlock, how to choose an RTOS, Integration and testing of Embedded hardware and firmware, Embedded system Development Environment – Block diagram (excluding Keil).

Operating System Basics:

The Operating System acts as a bridge between the user applications/tasks and the underlying system resources through a set of system functionalities and services OS manages the system resources and makes them available to the user applications/tasks on a need basis

The primary functions of an Operating system are

  1. Make the system convenient to use
  2. Organize and manage the system resources efficiently and correctly

Fig. The Operating System Architecture

Following are some of important functions of an operating System.

An Operating System provides services to both the users and to the programs. It provides programs an environment to execute.

The Kernel

The kernel is the core of the operating system. It is responsible for managing the system resources and the communication among the hardware and other system services. Kernel acts as the abstraction layer between system resources and user applications.

Kernel contains a set of system libraries and services. For a general purpose OS, the kernel contains different services like

  1. Process Management:

  1. Main Memory Management:

The main memory is central to the operation of a modern computer system. Main memory is a large array of words or bytes ranging in size from hundreds of thousand to billions. Main memory stores the quickly accessible data shared by the CPU & I/O device. The central processor reads instruction from main memory during instruction fetch cycle & it both reads

&writes data from main memory during the data fetch cycle. The main memory is generally the only large storage device that the CPU is able to address & access directly. For example, for the CPU to process data from disk. Those data must first be transferred to main memory by CPU generated E/O calls. Instruction must be in memory for the CPU to execute them. The OS is responsible for the following activities in connection with memory management.

  1. File Management:

File management is one of the most important components of an OS computer can store information on several different types of physical media magnetic tape, magnetic disk & optical disk are the most common media. Each medium is controlled by a device such as disk drive or tape drive those has unique characteristics. These characteristics include access speed, capacity, data transfer rate & access method (sequential or random).For convenient use of computer system the OS provides a uniform logical view of information storage. The OS abstracts from the physical properties of its storage devices to define a logical storage unit the file. A file is collection of related information defined by its creator. The OS is responsible for the following activities of file management.

  1. I/O System Management:

One of the purposes of an OS is to hide the peculiarities of specific hardware devices from the user. For example, in UNIX the peculiarities of I/O devices are hidden from the bulk of the OS itself by the I/O subsystem. The I/O subsystem consists of:

  1. Secondary Storage Management:

The main purpose of computer system is to execute programs. These programs with the data they access must be in main memory during execution. As the main memory is too small to accommodate all data & programs & because the data that it holds are lost when power is lost. The computer system must provide secondary storage to back-up main memory. Most modern computer systems are disks as the storage medium to store data & program. The operating system is responsible for the following activities of disk management.

Because secondary storage is used frequently it must be used efficiently.

Networking:

A distributed system is a collection of processors that don’t share memory peripheral devices or a clock. Each processor has its own local memory & clock and the processor communicate with one another through various communication lines such as high speed buses or networks. The processors in the system are connected through communication networks which are configured in a number of different ways. The communication network design must consider message routing & connection strategies are the problems of connection & security.

Protection or security:

If a computer system has multi users & allow the concurrent execution of multiple processes then the various processes must be protected from one another’s activities. For that purpose, mechanisms ensure that files, memory segments, CPU & other resources can be operated on by only those processes that have gained proper authorization from the OS.

Interrupt Handling

Kernel provides handler mechanism for all external /internal interrupts generated by the system. These are some of the important services offered by the kernel of an operating system. It does not mean that a kernel contains no more than components/ services or more number

of components/services.

Kernel Space and User Space

Monolithic Kernel

Microkernel

Types of Operating Systems:

Depending on the type of kernel and kernel services, purpose and type of computing systems where the OS is deployed and the responsiveness to applications, Operating Systems are classified into

  1. General Purpose Operating System (GPOS)

  1. Real Time Purpose Operating System (RTOS)

  1. The Real Time Kernel

The kernel of a Real Time Operating System is referred as Real Time kernel. In complement to the conventional OS kernel, the Real Time kernel is highly specialized and it contains only the minimal set of services required for running the user applications/tasks. The basic functions of a Real Time kernel are

Task/Process Management

Deals with setting up the memory space for the tasks, loading the task’s code into the memory space, allocating system resources, setting up a Task Control Block (TCB) for the task and task/process termination/deletion. A Task Control Block (TCB) is used for holding the information corresponding to a task. TCB usually contains the following set of information

Memory Management

Interrupt Handling

Time Management

232 * 10-6/ (24 * 60 * 60) =~ 0.0497 Days = 1.19 hrs

If the ‘Timer tick’ interval is 1 millisecond, the System time register will reset in 232 * 10-3 / (24 * 60 * 60) = 497 Days = 49.7 Days =~ 50 Days

  1. Hard Real-time System

The presence of Human in the loop (HITL) for tasks introduces un-expected delays in the task execution. Most of the Hard Real Time Systems are automatic and does not contain a ‘human in the loop’.

  1. Soft Real-time System

Tasks, Processes & Threads

The structure of a Processes

Memory organization of a Processes

Process States & State Transition

Created

Incepted into memory

Ready

Blocked

Running

Execution Completion

Completed

Threads

The Concept of multithreading

Use of multiple threads to execute a process brings the following advantage.

Thread Standards:

Thread standards deal with the different standards available for thread creation and management. These standards are utilized by the Operating Systems for thread creation and thread management. It is a set of thread class libraries. The commonly available thread class libraries are

POSIX Threads: POSIX stands for Portable Operating System Interface. The POSIX.4 standard deals with the Real Time extensions and POSIX.4a standard deals with thread extensions. The POSIX standard library for thread creation and management is ‘Pthreads’. ‘Pthreads’ library defines the set of POSIX thread creation and management functions in ‘C’ language.

POSIX Thread Creation

int pthread_create(pthread_t *new_thread_ID, const pthread_attr_t *attribute, void * (*start_function)(void *), void *arguments);

Creates a new thread for running the function start_function. Here pthread_t is the handle to the newly created thread and pthread_attr_1 is the data type for holding the thread attributes. ‘start_function’ is the function the thread is going to execute and arguments is the arguments for start_function. On successful creation of a Pthread, pthread_create( ) associates the Thread control block (TCB) corresponding to the newly created thread to the variable of type pthread_t.

The primitive

Int pthread_join (pthread_t new_thread, void* *thread_status);

Blocks the current thread and waits until the completion of the thread pointed by it.

All the POXIS ‘thread calls’ returns an integer. A return value of zero indicates the success of the call. It is always good to check the return value of each call.

Thread pre-emption

Thread pre-emption is the act of pre-empting the currently running thread (stopping the currently running thread temporarily).

Differences between Thread V/s Process

Preemptive scheduling

  1. Preemptive SJF Scheduling/ Shortest Remaining Time (SRT)

Ex 1): Three processes with process IDs P1, P2, P3 with estimated completion time 10, 5, 7 milliseconds respectively enters the ready queue together. A new process P4 with estimated completion time 2ms enters the ‘Ready’ queue after 2ms. Assume all the processes contain only CPU operation and no I/O operations are involved.

The waiting time for all the processes are given as

Waiting Time for P2 = 0 ms + (4 -2) ms = 2ms (P2 starts executing first and is interrupted by P4 and has to wait till the completion of P4 to get the next CPU slot)

Waiting Time for P4 = 0 ms (P4 starts executing by preempting P2 since the execution time for completion of P4 (2ms) is less than that of the Remaining time for execution completion of P2 (Here it is 3ms))

Waiting Time for P3 = 7 ms (P3 starts executing after completing P4 and P2) Waiting Time for P1 = 14 ms (P1 starts executing after completing P4, P2 and P3) Average waiting time        = (Waiting time for all the processes) / No. of Processes

= (Waiting time for (P4+P2+P3+P1)) / 4

= (0 + 2 + 7 + 14)/4 = 23/4

= 5.75 milliseconds

Turn Around Time (TAT) for P2 = 7 ms        (Time spent in Ready Queue + Execution Time)

Turn Around Time (TAT) for P4 = 2 ms (Time spent in Ready Queue + Execution Time = (Execution Start Time – Arrival Time) + Estimated Execution Time = (2-2) + 2)

Turn Around Time (TAT) for P3 = 14 ms        (Time spent in Ready Queue + Execution Time) Turn Around Time (TAT) for P1 = 24 ms        (Time spent in Ready Queue + Execution Time)

Average Turn Around Time        = (Turn Around Time for all the processes) / No. of Processes

= (Turn Around Time for (P2+P4+P3+P1)) / 4

= (7+2+14+24)/4 = 47/4

= 11.75 milliseconds

  1. Round Robin (RR) Scheduling:

Ex 2): Three processes with process IDs P1, P2, P3 with estimated completion time 6, 4, 2 milliseconds respectively, enters the ready queue together in the order P1, P2, P3. Calculate the waiting time and Turn Around Time (TAT) for each process and the Average waiting time and Turn Around Time (Assuming there is no I/O waiting for the processes) in RR algorithm with Time slice= 2ms.

The waiting time for all the processes are given as

Waiting Time for P1 = 0 + (6-2) + (10-8) = 0+4+2= 6ms (P1 starts executing first and waits for two time slices to get execution back and again 1 time slice for getting CPU time)

Waiting Time for P2 = (2-0) + (8-4) = 2+4 = 6ms (P2 starts executing after P1 executes for 1 time slice and waits for two time slices to get the CPU time)

Waiting Time for P3 = (4 -0) = 4ms (P3 starts executing after completing the first time slices for P1 and P2 and completes its execution in a single time slice.)

Average waiting time        = (Waiting time for all the processes) / No. of Processes

= (Waiting time for (P1+P2+P3)) / 3

= (6+6+4)/3 = 16/3

= 5.33 milliseconds

Turn Around Time (TAT) for P1 = 12 ms        (Time spent in Ready Queue + Execution Time) Turn Around Time (TAT) for P2 = 10 ms        (-Do-)

Turn Around Time (TAT) for P3 = 6 ms        (-Do-)

Average Turn Around Time        = (Turn Around Time for all the processes) / No. of        Processes

= (Turn Around Time for (P1+P2+P3)) / 3

= (12+10+6)/3 = 28/3

= 9.33 milliseconds

  1. Priority based Scheduling

Ex 3): Three processes with process IDs P1, P2, P3 with estimated completion time 10, 5, 7 milliseconds and priorities 1, 3, 2 (0- highest priority, 3 lowest priority) respectively enters the ready queue together. A new process P4 with estimated completion time 6ms and priority 0 enters the ‘Ready’ queue after 5ms of start of execution of P1. Assume all the processes contain only CPU operation and no I/O operations are involved.

The waiting time for all the processes are given as

Waiting Time for P1 = 0 + (11-5) = 0+6 =6 ms (P1 starts executing first and gets preempted by P4 after 5ms and again gets the CPU time after completion of P4)

Waiting Time for P4 = 0 ms (P4 starts executing immediately on entering the ‘Ready’ queue, by preempting P1)

Waiting Time for P3 = 16 ms (P3 starts executing after completing P1 and P4) Waiting Time for P2 = 23 ms (P2 starts executing after completing P1, P4 and P3) Average waiting time        = (Waiting time for all the processes) / No. of Processes

= (Waiting time for (P1+P4+P3+P2)) / 4

= (6 + 0 + 16 + 23)/4 = 45/4

= 11.25 milliseconds

Turn Around Time (TAT) for P1 = 16 ms (Time spent in Ready Queue + Execution Time)

Turn Around Time (TAT) for P4 = 6ms (Time spent in Ready Queue + Execution Time = (Execution Start Time – Arrival Time) + Estimated Execution Time = (5-5) + 6 = 0 + 6)

Turn Around Time (TAT) for P3 = 23 ms (Time spent in Ready Queue + Execution Time) Turn Around Time (TAT) for P2 = 28 ms (Time spent in Ready Queue + Execution Time) Average Turn Around Time        = (Turn Around Time for all the processes) / No. of Processes

= (Turn Around Time for (P2+P4+P3+P1)) / 4

= (16+6+23+28)/4 = 73/4

= 18.25 milliseconds

Task Communication:

In a multitasking system, multiple tasks/processes run concurrently (in pseudo parallelism) and each process may or may not interact between. Based on the degree of interaction, the processes /tasks running on an OS are classified as

The co-operating processes exchanges information and communicate through

Inter Process (Task) Communication (IPC)

Shared Memory

  1. Pipes:

‘Pipe’ is a section of the shared memory used by processes for communicating. Pipes follow the client-server architecture. A process which creates a pipe is known as pipe server and a process which connects to a pipe is known as pipe client. A pipe can be considered as a conduit for information flow and has two conceptual ends. It can be unidirectional, allowing information flow in one direction or bidirectional allowing bi- directional information flow. A unidirectional pipe allows the process connecting at one end of the pipe to write to the pipe and the process connected at the other end of the pipe to read the data, whereas a bi- directional pipe allows both reading and writing at one end.

Process 1 Write


Process 2 Read

The implementation of ‘Pipes’ is OS dependent. Microsoft® Windows Desktop Operating Systems support two types of ‘Pipes’ for Inter Process Communication. Namely;

Anonymous Pipes: The anonymous pipes are unnamed, unidirectional pipes used for data transfer between two processes.

Named Pipes: Named pipe is a named, unidirectional or bi-directional pipe for data exchange between processes. Like anonymous pipes, the process which creates the named pipe is known as pipe server. A process which connects to the named pipe is known as pipe client. With named pipes, any process can act as both client and server allowing point-to-point communication. Named pipes can be used for communicating between processes running on the same machine or between processes running on different machines connected to a network.

  1. Memory Mapped Objects:

Message Passing

  1. Message Queues:

Concept of Message Queue

  1. Mailbox:

  1. Signal:

Remote Procedure Call (RPC)

Processes running on different CPUs which are networked

Processes running on same CPU

Concept of Remote Procedure Call (RPC) for IPC

Stream sockets are connection oriented and they use TCP to establish a reliable connection. Datagram Sockets rely on UDP for establishing a connection.

Task Synchronization

Task Synchronization Issues – Racing

Have a look at the following piece of code

From a programmer perspective, the value of counter will be 10 at the end of execution of processes A & B. But it need not be always. program statement counter++; looks like a single statement from a high level programming language (C Language) perspective. The low level implementation of this statement is dependent on the underlying processor instruction set and the (cross) compiler in use. The low level implementation of the high level program statement counter++; under Windows XP operating system running on an Intel Centrino Duo processor is given below. The code snippet is compiled with Microsoft Visual Studio 6.0 compiler.

At the processor instruction level, the value of the variable counter is loaded to the Accumulator register (EAX Register). The memory variable counter is represented using a pointer. The base pointer register (EBP Register) is used for pointing to the memory variable counter. After loading the contents of the variable counter to the Accumulator, the Accumulator content is incremented by one using the add instruction. Finally the content of Accumulator is loaded to the memory location which represents the variable counter. Both the processes Process A and Process B contain the program statement counter++; Translating this into the machine instruction.

Process A

Process B

mov eax,dword ptr [ebp-4] add eax,1

mov dword ptr [ebp-4],eax

mov eax,dword ptr [ebp-4] add eax,1

mov dword ptr [ebp-4],eax

Imagine a situation where a process switching (context switching) happens from Process A to Process B when Process A is executing the counter++; statement. Process A accomplishes the counter++; statement through three different low level instructions. Now imagine that the process switching happened at the point where Process A executed the low level instruction mov eax,dword ptr [ebp-4] and is about to execute the next instruction add eax,1. The scenario is illustrated below.

Process B increments the shared variable ‘counter’ in the middle of the operation where Process A tries to increment it. When Process A gets the CPU time for execution, it starts from the point where it got interrupted (If Process B is also using the same registers eax and ebp for executing counter++; instruction, the original content of these registers will be saved (PUSHed) by Process B before using it and the contents will be retrieved (POPed) after finishing the operation. Hence the content of eax and ebp remains intact irrespective of context switching). Though the variable counter is incremented by Process B, Process A is unaware of it and it increments the variable with the old value. This leads to the loss of one increment for the variable counter.

Task Synchronization Issues – Deadlock

Deadlock is the condition in which a process is waiting for a resource held by another process which is waiting for a resource held by the first process. Process A holds a resource ‘x’ and it wants a resource ‘y’ held by Process B. Process B is currently holding resource ‘y’ and it wants the resource ‘x’ which is currently held by Process A. Both hold the respective resources and they compete each other to get the resource held by the respective processes.

Mutual Exclusion: The criteria that only one process can hold a resource at a time. Meaning processes should access shared resources with mutual exclusion. Typical example is the accessing of display device in an embedded device

Hold & Wait: The condition in which a process holds a shared resource by acquiring the lock controlling the shared access and waiting for additional resources held by other processes

No Resource Preemption: The criteria that Operating System cannot take back a resource from a process which is currently holding it and the resource can only be released voluntarily by the process holding it.

Circular Wait: A process is waiting for a resource which is currently held by another process which in turn is waiting for a resource held by the first process. In general there exists a set of waiting process P0, P1 …. Pn with P0 is waiting for a resource held by P1 and P1 is waiting for a resource held by P0, ……, Pn is waiting for a resource held by P0 and P0 is waiting for a resource held by Pn and so on… This forms a circular wait queue.

‘Deadlock’ is a result of the combined occurrence of these four conditions listed above. These conditions are first described by E. G. Coffman in 1971 and it is popularly known as Coffman conditions.

A smart OS may foresee the deadlock condition and will act proactively to avoid such a situation. Now if a deadlock occurred, how the OS responds to it? The reaction to deadlock condition by OS is non uniform. The OS may adopt any of the following techniques to detect and prevent deadlock conditions.

Ignore Deadlocks: Always assume that the system design is deadlock free. This is acceptable for the reason the cost of removing a deadlock is large compared to the chance of happening a deadlock. UNIX is an example for an OS following this principle. A life critical system cannot pretend that it is deadlock free for any reason.

Detect and Recover: This approach suggests the detection of a deadlock situation and recovery from it. This is similar to the deadlock condition that may arise at a traffic junction. When the vehicles from different directions compete to cross the junction, deadlock (traffic jam) condition is resulted. Once a deadlock (traffic jam) is happened at the junction, the only solution is to back up the vehicles from one direction and allow the vehicles from opposite direction to cross the junction. If the traffic is too high, lots of vehicles may have to be backed up to resolve the traffic jam. This technique is also known as ‘back up cars’ technique

Operating Systems keep a resource graph in their memory. The resource graph is updated on each resource request and release. A deadlock condition can be detected by analyzing the resource graph by graph analyzer algorithms. Once a deadlock condition is detected, the system can terminate a process or preempt the resource to break the deadlocking cycle.

Avoid Deadlocks: Deadlock is avoided by the careful resource allocation techniques by the Operating System. It is similar to the traffic light mechanism at junctions to avoid the traffic jams.

Prevent Deadlocks: Prevent the deadlock condition by negating one of the four conditions favoring the deadlock situation.

  1. A process must request all its required resource and the resources should be allocated before the process begins its execution.
  2. Grant resource allocation requests from processes only if the process does not hold a resource currently
  1. Release all the resources currently held by a process if a request made by the process for a new resource is not able to fulfill immediately.
  2. Add the resources which are preempted (released) to a resource list describing the resources which the process requires to complete its execution.
  3. Reschedule the process for execution only when the process gets its old resources and the new resource which is requested by the process.

Livelock: The Livelock condition is similar to the deadlock condition except that a process in livelock condition changes its state with time. While in deadlock a process enters in wait state for a resource and continues in that state forever without making any progress in the execution. In a livelock condition a process always do something but unable to make any progress in the execution completion. The livelock condition is better explained with the real world example, two people attempting to cross each other in a narrow corridor. Both of the persons move towards each side of the corridor to allow the opposite person to cross. Since the corridor is narrow, none of them are able to cross each other. Here both of the persons perform some action but still they are unable to achieve their target- Cross each other.

Starvation: In the task synchronization issue context, starvation is the condition in which a process does not get the resources required to continue its execution for a long time. As time progresses the process starves on resource. Starvation may arise due to various conditions like byproduct of preventive measures of deadlock, scheduling policies favoring high priority tasks and tasks with shortest execution time etc.

Integration and Testing of Embedded hardware and Firmware:

The Embedded System Development Environment:

The Development Environment consists of a Development computer (PC) or host, which acts as the heart of the development environment, Integrated Development Environment (IDE) tool for embedded firmware development and debugging, Electronic Design Automation (EDA)tool for Embedded Hardware design. An emulator hardware for debugging the target board, Signal sources (like function generator0 for simulating the inputs to the target board, Target hardware